package keer.httpinterface.utils;

import java.util.concurrent.ConcurrentHashMap;
import java.util.function.Supplier;

/**
 * CacheMap类继承自ConcurrentHashMap，提供了线程安全的缓存映射。
 * 它通过使用指定的键来缓存值，以避免重复计算或访问。
 * 这个类的主要功能是通过loadOrCreate方法来加载或创建缓存项。
 *
 * @param <K> 键的类型
 * @param <V> 值的类型
 */
public class CacheMap<K, V> extends ConcurrentHashMap<K, V> {

    /**
     * 加载或创建与给定键关联的值。
     * 如果map中已存在该键，则直接返回对应的值。
     * 如果map中不存在该键，则使用供应商函数生成一个新的值，将其添加到map中，并返回该值。
     * 此方法确保相同键的并发请求不会导致重复计算（通过双重检查锁定实现）。
     *
     * @param key 键，用于检索或创建值
     * @param supplier 一个供应商函数，用于在需要时生成新值
     * @return 与键关联的值，如果生成的新值为null，则返回null
     */
    public V loadOrCreate(K key, Supplier<V> supplier) {
        // 首先检查map中是否已存在该键，以避免不必要的同步操作
        if (containsKey(key)) {
            return get(key);
        }

        // 使用同步块确保并发安全
        synchronized (this) {
            // 再次检查map中是否已存在该键，以防其他线程在等待期间已添加该键
            if (containsKey(key)) {
                return get(key);
            }

            // 使用供应商函数生成新值
            V v = supplier.get();
            // 如果生成的值不为null，则将其添加到map中
            if (v != null) {
                put(key, v);
            }
            // 返回生成的值，无论是否添加到map中
            return v;
        }
    }
}
